﻿namespace XDesignerCommon
{
    using System;
    using System.Drawing;
    using ZYCommon;

    public sealed class RectangleCommon
    {
        private RectangleCommon()
        {
        }

        public static Rectangle AlignRect(Rectangle MainRect, int width, int height, int Align, int VAlign)
        {
            Rectangle rect = new Rectangle(0, 0, width, height);
            if (Align == 1)
            {
                rect.X = MainRect.Left;
            }
            else if (Align == 2)
            {
                rect.X = MainRect.Left + ((MainRect.Width - width) / 2);
            }
            else if (Align == 3)
            {
                rect.X = MainRect.Right - width;
            }
            if (VAlign == 1)
            {
                rect.Y = MainRect.Top;
                return rect;
            }
            if (VAlign == 2)
            {
                rect.Y = MainRect.Top + ((MainRect.Height - height) / 2);
                return rect;
            }
            if (VAlign == 3)
            {
                rect.Y = MainRect.Bottom - height;
            }
            return rect;
        }

        public static RectangleF AlignRect(RectangleF MainRect, float width, float height, int Align, int VAlign)
        {
            RectangleF rect = new RectangleF(0f, 0f, width, height);
            if (Align == 1)
            {
                rect.X = MainRect.Left;
            }
            else if (Align == 2)
            {
                rect.X = MainRect.Left + ((MainRect.Width - width) / 2f);
            }
            else if (Align == 3)
            {
                rect.X = MainRect.Right - width;
            }
            if (VAlign == 1)
            {
                rect.Y = MainRect.Top;
                return rect;
            }
            if (VAlign == 2)
            {
                rect.Y = MainRect.Top + ((MainRect.Height - height) / 2f);
                return rect;
            }
            if (VAlign == 3)
            {
                rect.Y = MainRect.Bottom - height;
            }
            return rect;
        }

        public static Point Center(Rectangle rect)
        {
            return new Point(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2));
        }

        public static PointF Center(RectangleF rect)
        {
            return new PointF(rect.Left + (rect.Width / 2f), rect.Top + (rect.Height / 2f));
        }

        public static Rectangle Center(Rectangle rect, Size size)
        {
            return new Rectangle(rect.Left + ((rect.Width - size.Width) / 2), rect.Top + ((rect.Height - size.Height) / 2), size.Width, size.Height);
        }

        public static RectangleF Center(RectangleF rect, SizeF size)
        {
            return new RectangleF(rect.Left + ((rect.Width - size.Width) / 2f), rect.Top + ((rect.Height - size.Height) / 2f), size.Width, size.Height);
        }

        public static int GetAcmeIndex(Rectangle vRect, Point p)
        {
            if (!vRect.IsEmpty)
            {
                if (p.Y == vRect.Y)
                {
                    if (p.X == vRect.X)
                    {
                        return 0;
                    }
                    if (p.X == vRect.Right)
                    {
                        return 1;
                    }
                }
                else if (p.Y == vRect.Bottom)
                {
                    if (p.X == vRect.Right)
                    {
                        return 2;
                    }
                    if (p.X == vRect.X)
                    {
                        return 3;
                    }
                }
            }
            return -1;
        }

        public static int GetAcmeIndexF(RectangleF vRect, PointF p)
        {
            if (!vRect.IsEmpty)
            {
                if (p.Y == vRect.Y)
                {
                    if (p.X == vRect.X)
                    {
                        return 0;
                    }
                    if (p.X == vRect.Right)
                    {
                        return 1;
                    }
                }
                else if (p.Y == vRect.Bottom)
                {
                    if (p.X == vRect.Right)
                    {
                        return 2;
                    }
                    if (p.X == vRect.X)
                    {
                        return 3;
                    }
                }
            }
            return -1;
        }

        public static Point GetAcmePos(Rectangle vRect, int AcmeIndex)
        {
            switch (AcmeIndex)
            {
                case 0:
                    return vRect.Location;

                case 1:
                    return new Point(vRect.Right, vRect.Y);

                case 2:
                    return new Point(vRect.Right, vRect.Bottom);

                case 3:
                    return new Point(vRect.X, vRect.Bottom);
            }
            return Point.Empty;
        }

        public static PointF GetAcmePos(RectangleF vRect, int AcmeIndex)
        {
            switch (AcmeIndex)
            {
                case 0:
                    return vRect.Location;

                case 1:
                    return new PointF(vRect.Right, vRect.Y);

                case 2:
                    return new PointF(vRect.Right, vRect.Bottom);

                case 3:
                    return new PointF(vRect.X, vRect.Bottom);
            }
            return PointF.Empty;
        }

        public static Point GetBorderPoint(int intLeft, int intTop, int intWidth, int intHeight, int iPos, int iSplit)
        {
            Point myPoint = Point.Empty;
            if (iSplit > 0)
            {
                iPos = iPos % (iSplit * 4);
                if (iPos < 0)
                {
                    iPos += iSplit * 4;
                }
                if ((iPos >= 0) && (iPos < iSplit))
                {
                    myPoint.X = intLeft + ((intWidth * iPos) / iSplit);
                    myPoint.Y = intTop;
                }
                else
                {
                    if ((iPos >= iSplit) && (iPos < (iSplit * 2)))
                    {
                        myPoint.X = intLeft + intWidth;
                        myPoint.Y = intTop + ((intHeight * (iPos - iSplit)) / iSplit);
                        return myPoint;
                    }
                    if ((iPos >= (iSplit * 2)) && (iPos < (iSplit * 3)))
                    {
                        myPoint.X = intLeft + ((intWidth * ((iSplit * 3) - iPos)) / iSplit);
                        myPoint.Y = intTop + intHeight;
                    }
                    else
                    {
                        myPoint.X = intLeft;
                        myPoint.Y = intTop + ((intHeight * ((iSplit * 4) - iPos)) / iSplit);
                    }
                }
            }
            return myPoint;
        }

        public static PointF GetBorderPoint(float intLeft, float intTop, float intWidth, float intHeight, int iPos, int iSplit)
        {
            PointF myPoint = PointF.Empty;
            if (iSplit > 0)
            {
                iPos = iPos % (iSplit * 4);
                if (iPos < 0)
                {
                    iPos += iSplit * 4;
                }
                if ((iPos >= 0) && (iPos < iSplit))
                {
                    myPoint.X = intLeft + ((intWidth * iPos) / ((float) iSplit));
                    myPoint.Y = intTop;
                }
                else
                {
                    if ((iPos >= iSplit) && (iPos < (iSplit * 2)))
                    {
                        myPoint.X = intLeft + intWidth;
                        myPoint.Y = intTop + ((intHeight * (iPos - iSplit)) / ((float) iSplit));
                        return myPoint;
                    }
                    if ((iPos >= (iSplit * 2)) && (iPos < (iSplit * 3)))
                    {
                        myPoint.X = intLeft + ((intWidth * ((iSplit * 3) - iPos)) / ((float) iSplit));
                        myPoint.Y = intTop + intHeight;
                    }
                    else
                    {
                        myPoint.X = intLeft;
                        myPoint.Y = intTop + ((intHeight * ((iSplit * 4) - iPos)) / ((float) iSplit));
                    }
                }
            }
            return myPoint;
        }

        public static Rectangle GetInnerRectangle(Rectangle rect, StringAlignment Align, StringAlignment LineAlign, Size InnerRectSize)
        {
            int left = 0;
            int top = 0;
            if (Align == StringAlignment.Near)
            {
                left = rect.Left;
            }
            else if (Align == StringAlignment.Center)
            {
                left = rect.Left + ((rect.Width - InnerRectSize.Width) / 2);
            }
            else
            {
                left = rect.Right - InnerRectSize.Width;
            }
            if (LineAlign == StringAlignment.Near)
            {
                top = rect.Top;
            }
            else if (LineAlign == StringAlignment.Center)
            {
                top = rect.Top + ((rect.Height - InnerRectSize.Height) / 2);
            }
            else
            {
                top = rect.Bottom - InnerRectSize.Height;
            }
            return new Rectangle(left, top, InnerRectSize.Width, InnerRectSize.Height);
        }

        public static RectangleF GetInnerRectangle(RectangleF rect, StringAlignment Align, StringAlignment LineAlign, SizeF InnerRectSize)
        {
            float left = 0f;
            float top = 0f;
            if (Align == StringAlignment.Near)
            {
                left = rect.Left;
            }
            else if (Align == StringAlignment.Center)
            {
                left = rect.Left + ((rect.Width - InnerRectSize.Width) / 2f);
            }
            else
            {
                left = rect.Right - InnerRectSize.Width;
            }
            if (LineAlign == StringAlignment.Near)
            {
                top = rect.Top;
            }
            else if (LineAlign == StringAlignment.Center)
            {
                top = rect.Top + ((rect.Height - InnerRectSize.Height) / 2f);
            }
            else
            {
                top = rect.Bottom - InnerRectSize.Height;
            }
            return new RectangleF(left, top, InnerRectSize.Width, InnerRectSize.Height);
        }

        public static Rectangle GetMiddleRectangle(Rectangle rect1, Rectangle rect2, double rate)
        {
            int left = rect1.Left + ((int) ((rect2.Left - rect1.Left) * rate));
            int top = rect1.Top + ((int) ((rect2.Top - rect1.Top) * rate));
            int w = rect1.Width + ((int) ((rect2.Width - rect1.Width) * rate));
            return new Rectangle(left, top, w, rect1.Height + ((int) ((rect2.Height - rect1.Height) * rate)));
        }

        public static Rectangle GetRectangle(Point p1, Point p2)
        {
            return GetRectangle(p1.X, p1.Y, p2.X, p2.Y);
        }

        public static RectangleF GetRectangle(PointF p1, PointF p2)
        {
            return GetRectangle(p1.X, p1.Y, p2.X, p2.Y);
        }

        public static Rectangle GetRectangle(int x1, int y1, int x2, int y2)
        {
            Rectangle myRect = Rectangle.Empty;
            if (x1 < x2)
            {
                myRect.X = x1;
                myRect.Width = x2 - x1;
            }
            else
            {
                myRect.X = x2;
                myRect.Width = x1 - x2;
            }
            if (y1 < y2)
            {
                myRect.Y = y1;
                myRect.Height = y2 - y1;
            }
            else
            {
                myRect.Y = y2;
                myRect.Height = y1 - y2;
            }
            if (myRect.Width < 1)
            {
                myRect.Width = 1;
            }
            if (myRect.Height < 1)
            {
                myRect.Height = 1;
            }
            return myRect;
        }

        public static RectangleF GetRectangle(float x1, float y1, float x2, float y2)
        {
            RectangleF myRect = RectangleF.Empty;
            if (x1 < x2)
            {
                myRect.X = x1;
                myRect.Width = x2 - x1;
            }
            else
            {
                myRect.X = x2;
                myRect.Width = x1 - x2;
            }
            if (y1 < y2)
            {
                myRect.Y = y1;
                myRect.Height = y2 - y1;
            }
            else
            {
                myRect.Y = y2;
                myRect.Height = y1 - y2;
            }
            if (myRect.Width < 1f)
            {
                myRect.Width = 1f;
            }
            if (myRect.Height < 1f)
            {
                myRect.Height = 1f;
            }
            return myRect;
        }

        public static Rectangle GetSquare(Rectangle rect)
        {
            if (rect.Width == rect.Height)
            {
                return rect;
            }
            if (rect.Width > rect.Height)
            {
                return new Rectangle(rect.Left + ((rect.Width - rect.Height) / 2), rect.Top, rect.Height, rect.Height);
            }
            return new Rectangle(rect.Left, rect.Top + ((rect.Height - rect.Width) / 2), rect.Width, rect.Width);
        }

        public static RectangleF GetSquare(RectangleF rect)
        {
            if (rect.Width == rect.Height)
            {
                return rect;
            }
            if (rect.Width > rect.Height)
            {
                return new RectangleF(rect.Left + ((rect.Width - rect.Height) / 2f), rect.Top, rect.Height, rect.Height);
            }
            return new RectangleF(rect.Left, rect.Top + ((rect.Height - rect.Width) / 2f), rect.Width, rect.Width);
        }

        public static Size InnerRoteteRectangleSize(int Width, int Height, double angle)
        {
            if ((Width <= 0) || (Height <= 0))
            {
                return Size.Empty;
            }
            double a = Math.Atan2((double) Height, (double) Width);
            double r = Math.Sqrt((double) ((Width * Width) + (Height * Height))) / 2.0;
            double w = r * Math.Cos(a - angle);
            double h = r * Math.Sin(a + angle);
            double rate = (w * 2.0) / ((double) Width);
            if (rate < ((h * 2.0) / ((double) Height)))
            {
                rate = (h * 2.0) / ((double) Height);
            }
            return new Size((int) (((double) Width) / rate), (int) (((double) Height) / rate));
        }

        public static SizeF InnerRoteteRectangleSize(float Width, float Height, double angle)
        {
            if ((Width <= 0f) || (Height <= 0f))
            {
                return SizeF.Empty;
            }
            double a = Math.Atan2((double) Height, (double) Width);
            double r = Math.Sqrt((double) ((Width * Width) + (Height * Height))) / 2.0;
            double w = r * Math.Cos(a - angle);
            double h = r * Math.Sin(a + angle);
            double rate = (w * 2.0) / ((double) Width);
            if (rate < ((h * 2.0) / ((double) Height)))
            {
                rate = (h * 2.0) / ((double) Height);
            }
            return new SizeF((float) (((double) Width) / rate), (float) (((double) Height) / rate));
        }

        public static Point MoveInto(Point p, Rectangle Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (p.X < Bounds.Left)
                {
                    p.X = Bounds.Left;
                }
                if (p.X >= Bounds.Right)
                {
                    p.X = Bounds.Right;
                }
                if (p.Y < Bounds.Top)
                {
                    p.Y = Bounds.Top;
                }
                if (p.Y >= Bounds.Bottom)
                {
                    p.Y = Bounds.Bottom;
                }
            }
            return p;
        }

        public static PointF MoveInto(PointF p, RectangleF Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (p.X < Bounds.Left)
                {
                    p.X = Bounds.Left;
                }
                if (p.X >= Bounds.Right)
                {
                    p.X = Bounds.Right;
                }
                if (p.Y < Bounds.Top)
                {
                    p.Y = Bounds.Top;
                }
                if (p.Y >= Bounds.Bottom)
                {
                    p.Y = Bounds.Bottom;
                }
            }
            return p;
        }

        public static Rectangle MoveInto(Rectangle rect, Rectangle Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (rect.Right > Bounds.Right)
                {
                    rect.X = Bounds.Right - rect.Width;
                }
                if (rect.Bottom > Bounds.Bottom)
                {
                    rect.Y = Bounds.Bottom - rect.Height;
                }
                if (rect.X < Bounds.Left)
                {
                    rect.X = Bounds.Left;
                }
                if (rect.Y < Bounds.Top)
                {
                    rect.Y = Bounds.Top;
                }
            }
            return rect;
        }

        public static RectangleF MoveInto(RectangleF rect, RectangleF Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (rect.Right > Bounds.Right)
                {
                    rect.X = Bounds.Right - rect.Width;
                }
                if (rect.Bottom > Bounds.Bottom)
                {
                    rect.Y = Bounds.Bottom - rect.Height;
                }
                if (rect.X < Bounds.Left)
                {
                    rect.X = Bounds.Left;
                }
                if (rect.Y < Bounds.Top)
                {
                    rect.Y = Bounds.Top;
                }
            }
            return rect;
        }

        public static int MoveXInto(int x, Rectangle Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (x < Bounds.Left)
                {
                    x = Bounds.Left;
                }
                else if (x > Bounds.Right)
                {
                    x = Bounds.Right;
                }
            }
            return x;
        }

        public static float MoveXInto(float x, RectangleF Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (x < Bounds.Left)
                {
                    x = Bounds.Left;
                }
                else if (x > Bounds.Right)
                {
                    x = Bounds.Right;
                }
            }
            return x;
        }

        public static int MoveYInto(int y, Rectangle Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (y < Bounds.Top)
                {
                    y = Bounds.Top;
                }
                else if (y > Bounds.Bottom)
                {
                    y = Bounds.Bottom;
                }
            }
            return y;
        }

        public static float MoveYInto(float y, RectangleF Bounds)
        {
            if (!Bounds.IsEmpty)
            {
                if (y < Bounds.Top)
                {
                    y = Bounds.Top;
                }
                else if (y > Bounds.Bottom)
                {
                    y = Bounds.Bottom;
                }
            }
            return y;
        }

        public static bool PaintInvalidSize(int width, int height)
        {
            return (((width > 0) && (height >= 0)) || ((height > 0) && (width >= 0)));
        }

        public static bool PaintInvalidSize(float width, float height)
        {
            return (((width > 0f) && (height >= 0f)) || ((height > 0f) && (width >= 0f)));
        }

        public static Rectangle ReSize(Rectangle rect, int dsize)
        {
            return new Rectangle(rect.Left, rect.Top, rect.Width + dsize, rect.Height + dsize);
        }

        public static RectangleF ReSize(RectangleF rect, float dsize)
        {
            return new RectangleF(rect.Left, rect.Top, rect.Width + dsize, rect.Height + dsize);
        }

        public static Rectangle RotateRectangle(Point o, Rectangle rect, double angle)
        {
            Point[] ps = To4Points(rect);
            for (int iCount = 0; iCount < ps.Length; iCount++)
            {
                ps[iCount] = MathCommon.RotatePoint(o, ps[iCount], angle);
            }
            return PointBuffer.GetBounds(ps);
        }

        public static RectangleF RotateRectangle(PointF o, RectangleF rect, double angle)
        {
            PointF[] ps = To4Points(rect);
            for (int iCount = 0; iCount < ps.Length; iCount++)
            {
                ps[iCount] = MathCommon.RotatePoint(o, ps[iCount], angle);
            }
            return PointBuffer.GetBounds(ps);
        }

        public static Rectangle SetCenter(Rectangle rect, int x, int y)
        {
            return new Rectangle(x - (rect.Width / 2), y - (rect.Height / 2), rect.Width, rect.Height);
        }

        public RectangleF SetCenter(RectangleF rect, float x, float y)
        {
            return new RectangleF(x - ((float) (((double) rect.Width) / 2.0)), y - ((float) (((double) rect.Height) / 2.0)), rect.Width, rect.Height);
        }

        public static Point[] To3Points(Rectangle rect)
        {
            return new Point[] { new Point(rect.X, rect.Y), new Point(rect.Right, rect.Y), new Point(rect.Right, rect.Bottom) };
        }

        public static PointF[] To3Points(RectangleF rect)
        {
            return new PointF[] { new PointF(rect.X, rect.Y), new PointF(rect.Right, rect.Y), new PointF(rect.Right, rect.Bottom) };
        }

        public static Point[] To4Points(Rectangle rect)
        {
            return new Point[] { new Point(rect.X, rect.Y), new Point(rect.Right, rect.Y), new Point(rect.Right, rect.Bottom), new Point(rect.Left, rect.Bottom) };
        }

        public static PointF[] To4Points(RectangleF rect)
        {
            return new PointF[] { new PointF(rect.X, rect.Y), new PointF(rect.Right, rect.Y), new PointF(rect.Right, rect.Bottom), new PointF(rect.Left, rect.Bottom) };
        }

        public static Point[] To5Points(Rectangle rect)
        {
            Point[] p=null;
            return new Point[] { new Point(rect.X, rect.Y), new Point(rect.Right, rect.Y), new Point(rect.Right, rect.Bottom), new Point(rect.Left, rect.Bottom), p[0] };
        }

        public static PointF[] To5Points(RectangleF rect)
        {
            PointF[] p=null;
            return new PointF[] { new PointF(rect.X, rect.Y), new PointF(rect.Right, rect.Y), new PointF(rect.Right, rect.Bottom), new PointF(rect.Left, rect.Bottom), p[0] };
        }

        public static Rectangle ToRectangle(RectangleF rect)
        {
            return new Rectangle((int) rect.Left, (int) rect.Top, (int) rect.Width, (int) rect.Height);
        }

        public static RectangleF ToRectangleF(Rectangle rect)
        {
            return new RectangleF((float) rect.Left, (float) rect.Top, (float) rect.Width, (float) rect.Height);
        }
    }
}

